/* 
 * File:   Math.h
 * Author: RedEyedKiller
 *
 * Created on 24 Μάρτιος 2010, 7:00 μμ
 */

#ifndef _MATHEMATICS_H
#define	_MATHEMATICS_H

#include <cmath>

//this precision value is used only for floats
//its square is used for doubles
#define PRECISION 0.0001f

namespace Math
{

template<class NumType>
class Vector2Templ;

class Rect;
class Circle;

//enumeration type used by extented intersection methods

enum IntersectionType
{
    INTER_NO = 0,
    INTER_TOUCH,
    INTER_FULL,
    INTER_CONTAINS
};

/**
 * Returns true if number s a power of 2
 * @param number
 * @return 
 */
inline bool IsPowerOf2(int number)
{
    return (number &  (number-1));
}

// methods used for precision equality checking for floats and doubles

inline bool eq(double d1, double d2)
{
    return (std::abs(d1 - d2) <= (PRECISION * PRECISION));
}

inline bool BelongsInFace(int start,int end,int point)
{
    return (start <= point && point <= end);
}


/**
 * Linear interpolation between two values
 * @param time is a value between [0-1] 
 */
template<typename T>
T LinearInterpolation(const T& start,const T& end,float time)
{
    return start * (1-time) + end * time;
}

/**
 * Cosine interpolation between two values
 * @param time is a value between [0-1] 
 */
template<typename T>
T CosineInterpolation(const T& start,const T& end,float time)
{
   float time2 = (1 - std::cos( time * 3.141592653589793238462 ) ) /2;
   return(start * (1 - time2) + end * time2);
}

/**
 * Finds the two points of contact of two rects.
 * @param rect1
 * @param rect2
 * @param points An array of Vector2I[2]
 * @return
 */
int CommonPoints(const Rect& rect1,const Rect& rect2,Vector2Templ<int> points[]);

/**
 * Return strue if both numbers are negative or positive.
 */
bool SameSign(float a,float b);

/**
 * Return the float number whose absolute value is the least.
 */
float AbsoluteMin(float a, float b);

/**
 * Return the float number whose absolute value is the least.
 */
float AbsoluteMax(float a, float b);

/**
 * Return true if thea absolute value of a is lesser than the absolute value of b.
 */
bool IsAbsoluteMax(float a, float b);

/**
 * Return true if thea absolute value of a is lesser than the absolute value of b.
 */
bool IsAbsoluteMin(float a, float b);

float RadiansToDegrees(float rad);
float DegreesToRadians(float deg);

/*Generic functions which return the distance between the centers of two objects*/

Vector2Templ<float> DistanceCenter(const Rect& rect1, const Rect& rect2);
Vector2Templ<float> DistanceCenter(const Circle& circle1, const Circle& circle2);
Vector2Templ<float> DistanceCenter(const Circle& circle, const Rect& rect);
Vector2Templ<float> DistanceCenter(const Circle& circle, const Vector2Templ<int>& vector);
Vector2Templ<float> DistanceCenter(const Rect& rect, const Vector2Templ<int>& vector);

/*Generic functions which return the distance between two objects*/

Vector2Templ<float> DistanceClosestPoint(const Rect& rect1, const Rect& rect2);
Vector2Templ<float> DistanceClosestPoint(const Circle& circle, const Vector2Templ<float>& vector);
Vector2Templ<float> DistanceClosestPoint(const Rect& rect1, const Vector2Templ<float>& vector);
Vector2Templ<float> DistanceClosestPoint(const Circle& circle1, const Circle& circle2);
Vector2Templ<float> DistanceClosestPoint(const Circle& circle, const Rect& rect);

/*Basic functions which return true if two object intersect with each other*/
/*they  return false on touch*/

bool Intersect(const Rect& rect1, const Rect& rect2);
bool Intersect(const Rect& rect, const Vector2Templ<int>& vec);
bool Intersect(const Rect& rect, const Vector2Templ<float>& vec);
bool Intersect(const Circle& circle, const Vector2Templ<int>& vec);
bool Intersect(const Circle& circle, const Vector2Templ<float>& vec);
bool Intersect(const Circle& circle, const Rect& rect);
bool Intersect(const Circle& circle1, const Circle& circle2);

/* these method in contrast with th simplified intersection methods
 * don't return true or false but no , touch or full intersevtion
 * more over though the axisinfo argument they return the vector
 * which discribes the intersection.
 * In case of intersection each element of this vector is equal
 * to the value by which the one shape overlaps the other.
 * for instance if a rect A intersects with rect B then
 *          AAA*****BBB  asume that * are the common parts of A and B
 * then the info vector will hold the value 5 for the x axis because
 * the two rects overlapp each other for 5 units*/

IntersectionType Intersect(const Rect& rect1, const Rect& rect2, Vector2Templ<float>& axisInfo);
IntersectionType Intersect(const Circle& circle, const Rect& rect, Vector2Templ<float>& axisInfo);
IntersectionType Intersect(const Circle& circle1, const Circle& circle2, Vector2Templ<float>& axisInfo);

bool OneAxisIntersection(int startA,int endA,int startB,int endB,int* diff);

};

#endif	/* _MATHEMATICS_H */
